package forum.server.domain;

import forum.server.controller.*;
import forum.server.persistence.Gender;
import forum.server.persistence.UserType;
import forum.shared.exceptions.*;
import java.security.NoSuchAlgorithmException;
import java.util.Date;


/**
 * This class represents a logged in user in the forum system.
 * Logged in user is created whenever a guest performs the "login" action.
 * Provides functionality of adding, deleting and modifying user posts.
 * @author Alon Furman
 */
public class LoggedInUser{    
	
	/**
     * A unique username for each user,
     * used as identification during login.
     */
    private String username;

    /**
     * A unique password for each user,
     * used as identification during login.
     * Stored as a result of 1-way hash function.
     */
    private String password;

    /**
     * User's personal information: first name, last name, gender, city name, birthday date.
     */
    private String firstName;
    private String lastName;
    private String email;

    private Gender gender;
    private String city;
    private Date birthday;
	private String connected; //currently connected or not.

    /**
     * Default constructor - for the DataManipulator.
     */
    public LoggedInUser(){
    	this.username = "default";
        this.password = "123456";
        this.firstName = "default";
        this.lastName = "default";
        this.email = "default";
        this.gender = Gender.MALE;
        this.city = "default";
        this.birthday = new Date();
        this.connected = "not connected";
    }
    
    /**
     * Constructor which creates a registered user just with the essential username
     * and password, without personal information.
     * @param username - The username that was chosen during registration.
     * @param password - The password that was chosen during registration.
     */
    public LoggedInUser(String username, String password) {
    	this.username = username;
        this.password = password;
        this.firstName = "default";
        this.lastName = "default";
        this.email = "default";
        this.gender = Gender.MALE;
        this.city = "default";
        this.birthday = new Date();
        this.connected = "not connected";
    }

    /**
     * Constructor which creates a fully detailed user including all personal information.
     * @param username - The username that was chosen during registration.
     * @param password - The password that was chosen during registration.
     * @param firstName - The user's first name.
     * @param lastName - The user's last name.
     * @param gender - The user's gender.
     * @param city - The user's city name.
     * @param birthday - The user's birthday date.
     */
    public LoggedInUser(String username, String password, String firstName,
            String lastName, String email, Gender gender, String city, Date birthday) {
        this.username = username;
        this.password = password;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
        this.city = city;
        this.birthday = birthday;
        this.connected = "not connected";
    }

    /**
     * Constructor which receives a moderator as a parameter and creates
     * a logged in user  with the moderator's data.
     * Used to support the demote moderator functionality in Admin class.
     * @param m - Moderator to demote.
     */
    public LoggedInUser(Moderator m){
        this(m.getUsername(),m.getPassword(),m.getFirstName(), m.getLastName(), m.getEmail(), m.getGender(),
                m.getCity(), m.getBirthday());
    }

    /**
     *
     * @return The user's birthday date.
     */
    public Date getBirthday() {
        return this.birthday;
    }

    /**
     * Sets the user's birthday date.
     * @param birthday - The new birthday date.
     */
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    /**
     *
     * @return The user's city name.
     */
    public String getCity() {
        return this.city;
    }

    /**
     * Sets the user's city name.
     * @param city- The new city name.
     */
    public void setCity(String city) {
        this.city = city;
    }

    /**
     *
     * @return The user's first name.
     */
    public String getFirstName() {
        return this.firstName;
    }

    /**
     * Sets the user's first name.
     * @param firstName - The new first name.
     */
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    /**
     *
     * @return the user's gender.
     */
    public Gender getGender() {
        return this.gender;
    }

    /**
     * Sets the user's gender.
     * @param gender - The new gender.
     */
    public void setGender(Gender gender) {
        this.gender = gender;
    }

    /**
     *
     * @return The user's last name.
     */
    public String getLastName() {
        return this.lastName;
    }

    /**
     * Sets the user's last name.
     * @param lastName - The new last name.
     */
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    /**
     * 
     * @return the user's email.
     */
    public String getEmail() {
    	return this.email;
    }
    
    /**
     * sets the user's email to 'newEmail'
     * @param newEmail the user's new email.
     */
    public void setEmail(String newEmail) {
    	this.email = newEmail;
    }
    
    /**
     *
     * @return The user's password.
     */
    public String getPassword() {
        return this.password;
    }

    /**
     * Sets the user's password.
     * @param password - The new password.
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     *
     * @return The user's username.
     */
    public String getUsername() {
        return this.username;
    }

    /**
     * Sets the user's username.
     * @param username - The new username.
     */
    public void setUsername(String username) {
        this.username = username;
    }


//    /**
//     * Checks whether the post is a reply to some other post and removes it.
//     * This function is used by the deletePost function in each user type.
//     * @param post - The post to remove.
//     */
//    protected void handlePostDeletion(Post p){
//        if (p.isReply()){
//            p.getFatherPost().removeReply(p);
//        }
//        for (Post post : p.getReplies()){
//        	handlePostDeletion(post);
//        }
//    }
//
//    /**
//     * Deletes a post from the forum.
//     * If the registered user is not the author of the post to be deleted an exception is thrown.
//     * @param post - The post to delete.
//     * @throws  UnauthorizedDeleteException - Thrown in case of illegal delete attempt.
//     */
//    public void deletePost(Post post) throws UnauthorizedDeleteException {
//        if (post.getAuthor().equals(this.username)){
//            handlePostDeletion(post);
//        }
//        else {
//            throw new UnauthorizedDeleteException("Registered user can't delete posts created by other user!");
//        }
//    }
    
    /**
     * Adds a new post containing the specified header and post content  to the forum.
     * @param header - The header of the post to be added.
     * @param postContent - The content of the post to be added.
     * @param postID - The ID of the newly created post.
     * @return The new post added to the forum.
     */
    public Post addPost(String header, PostContent postContent, int postId) {
        Post tPost = new Post(this.username, header, postContent, postId);
        return tPost;
    }

    /**
     * Modifies an existing post with a new post content only if  the user is the author
     * of the post to be modified.
     * Otherwise an exception is thrown to indicate violation of  modify rules.
     * @param post - The post to be modified.
     * @param aNewContent - New content for the post.
     * @return The post after modification.
     * @throws UnauthorizedOpException - Thrown in case of illegal modify attempt.
     */
    public Post modifyPost(Post post, PostContent aNewContent) throws UnauthorizedOpException {
        if (post.getAuthor().equals(this.username)){
           post.setContent(aNewContent);
           return post;
        }
        else{
            throw new UnauthorizedOpException("Registered user can't modify posts created by other user!");
        }
    }

    /**
     * Makes and returns a new reply.
     * @param header - The header of the post to be added.\
     * @param postContent - The post content of the new post to be added.
     * @param postID - The ID of the newly created post.
     * @param parentID - The postID to which the new post should be added as a reply.
     * @return The new post created as a reply.
     */
    public Post replyToPost(String header, PostContent postContent, 
    		int postID, int parentID) {
        return new Post(this.username, header, postContent, postID, parentID);
    }

    /**
     * The function validates if the password recieved matches the user's password.
     * Used as part of a login action.
     * @param password - The password to verify.
     * @return True if the password matches to the user's password, False otherwise.
     */
    public boolean validatePassword(String password) {
    	try {
    		return this.password.equals(Security.encryptPassword(password));
		} catch (NoSuchAlgorithmException e) {
    		MyLogger.getInstance().logException("Password encryption error: md5 is not supported", e);
			System.exit(1); // TODO refactor??
		}
		return false;
    }
    

 /**
  * Deletes a post from the forum.
  * If the registered user is not the author of the post to be deleted an exception is thrown.
  * @param post - The post to delete.
  * @throws  UnauthorizedOpException - Thrown in case of illegal delete attempt.
  */
 public void deletePost(Post post) throws UnauthorizedOpException {
     if (!(post.getAuthor().equals(this.username))){
    	 throw new UnauthorizedOpException("Registered user can't delete posts created by other user!");
     }
 }
    
    /**
     * The function is used to support the promote functionality in any type of user.
     * Due to the fact that only the admin can promote moderators an exception is thrown.
     * @param user - LoggedInUser to promote to moderator.
     * @return - The promoted Moderator.
     * @throws UnauthorizedOpException - thrown in case of a LoggedInUser trying to perform the operation.
     */
    public Moderator promoteModerator(LoggedInUser user) throws UnauthorizedOpException{
    	throw new UnauthorizedOpException("Regular users can't promote moderators");
    }

    /**
     * The function is used to support the demote functionality in any type of user.
     * Due to the fact that only the admin can demote moderators an exception is thrown.
     * @param moderator - Moderator to demote to LoggedInUser.
     * @return - The demoted LoggedinUser.
     * @throws UnauthorizedOpException - thrown in case of a LoggedInUser trying to perform the operation.
     */
    public LoggedInUser demoteModerator(Moderator moderator) throws UnauthorizedOpException{
    	throw new UnauthorizedOpException("Regular users can't demote moderators");
    }
    /**
     * 
     * @return the permission of the user.
     */
    public UserType getPermission(){
    	return UserType.LOGGEDINUSER;
    }

	/**
	 * @return the connected
	 */
	public String getConnected() {
		return connected;
	}

	/**
	 * @param connected the connected to set
	 */
	public void setConnected(String connected) {
		this.connected = connected;
	}
    
    
}
